#include<pthread.h>
#include<queue>
#include<iostream>
using namespace std;

const int default_task_cap = 5;
const int default_thread_cap = 5;

template<class T>
class ThreadPool
{
public:
  ThreadPool(int task_cap = default_task_cap,int thread_cap = default_thread_cap) 
    :_task_cap(task_cap),_thread_cap(thread_cap),_exit(false)
  {
    pthread_mutex_init(&_mtx,nullptr);
    pthread_cond_init(&_con,nullptr);
    pthread_cond_init(&_pro,nullptr);
  }

  ~ThreadPool()
  {
    pthread_mutex_destroy(&_mtx);
    pthread_cond_destroy(&_con);
    pthread_cond_destroy(&_pro);
  }

  void push(const T& val)
  {
    pthread_mutex_lock(&_mtx);
    if(_exit)
    {
      cout <<"退出标志位被设置,不能放入任务"<<endl;
      pthread_mutex_unlock(&_mtx);
      return;
    }
    while(_task_queue.size() >= _task_cap)
    {
      cout <<"当前任务太多...请等待线程池当中的线程执行任务完成,才能继续插入任务"<<endl;
      pthread_cond_wait(&_pro,&_mtx);
    }
    _task_queue.push(val);
    pthread_mutex_unlock(&_mtx);
    pthread_cond_signal(&_con);
  }

  void pop(T* out)
  {
    *out = _task_queue.front();
    _task_queue.pop();
  }

  static void* Routine(void* arg)
  {
    pthread_detach(pthread_self());
    ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(arg);
    while(1)
    {
      pthread_mutex_lock(&tp->_mtx); 
      while(tp->empty()) //任务队列为空
      {
        if(tp->_exit)
        {
          cout <<"任务队列为空&&退出标志位被设置... 线程:" <<pthread_self() <<"退出..." <<endl;
          tp->_thread_cap--;
          //注意:先解锁再销毁当前线程
          pthread_mutex_unlock(&tp->_mtx);
          pthread_exit(nullptr);
        }
        pthread_cond_wait(&tp->_con,&tp->_mtx);
      }
      T task;
      tp->pop(&task);
      pthread_mutex_unlock(&tp->_mtx);
      pthread_cond_signal(&tp->_pro);
      task();
    }
  }
  bool empty()
  {
    return _task_queue.empty();
  }

  int InitThreadPool()
  {
    int exit_cap = 0;
    for(int i = 0;i <  _thread_cap ;i++)
    {
      pthread_t tid;
      pthread_create(&tid,nullptr,Routine,(void*)this);
      if(tid < 0) exit_cap++;
    }
    _thread_cap -= exit_cap;
    cout <<"实际创建线程个数:"<<_thread_cap<<endl;
    return _thread_cap;
  }
  void DestrotThreadPool()
  {
    _exit = true;
    while(_thread_cap > 0)
      pthread_cond_signal(&_con);
  }

private:
  int _thread_cap;
  int _task_cap;
  bool _exit;
  pthread_mutex_t _mtx;
  pthread_cond_t _con;
  pthread_cond_t _pro;
  std::queue<T> _task_queue;
};

